const user = require('../database/tables/user')
const room = require('../database/tables/room')
const { sequelize } = require('../database/init')
const rp = require('request-promise')
const { formatBody } = require('../tools')
const { game } = require('../config/index')
const nanoid = require('nanoid')

module.exports = {
  // 用户注册
  async register (data, socket, cb) {
    let { uid, nickName, avatarUrl } = data
    console.log('register=>', data)
    if (!uid) {
      return cb(formatBody(0, 'uid不可为空'))
    }
    let isExist = await user.findOne({
      where: { uid }
    })
    if (isExist) {
      // let lastGroup
      // if (isExist.lastGroup) {
      //   lastGroup = await room.findOne({
      //     id: +isExist.lastGroup
      //   })
      // }
      // // 如果正在游戏中
      // if (lastGroup && lastGroup.state === '2') {
      //   // 断线重连
      //   socket.emit('recoverGame', { groupId: lastGroup.id })
      //   return cb(formatBody(1, '断线重连'))
      // }
      await user.update({
        socketId: socket.id,
        nickName, avatarUrl,
        state: '1'
      }, {
        where: {
          uid
        }
      })
      return cb(formatBody(1, '更新个人信息成功'))
    } else {
      await user.create({
        uid, nickName, avatarUrl,
        socketId: socket.id,
        isOnLine: 1,
        state: '1'
      })
      return cb(formatBody(1, '注册成功'))
    }
  },
  // 转发请求
  async transfer (data, socket, cb) {
    let { method, url, body } = data
    console.log(JSON.stringify(data))
    await rp({
      method,
      uri: url,
      body,
      json: true
    }).then(res => {
      console.log(res)
      cb(res)
    }).catch(err => {
      cb({
        ReturnCode: 'ERROR',
        ReturnMsg: '请求出错'
      })
    })
  },
  // 匹配接口
  // 首先查找匹配中的群组，如果没有，先创建群组，然后加入进去
  async match(data, socket, cb, io) {
    // 先查找所有处于匹配状态的人 然后取n个加入群组
    // console.log('match', data)
    let { uid, memberNum, type, coin, duration } = data
    console.log('match=>', data)
    if (!uid || !memberNum || !type || !coin || !duration) return cb(formatBody(0, 'uid,memberNum,type.coin,duration参数不可为空'))
    const isExistUser = await user.findOne({
      where: { uid }
    })
    if (!isExistUser) return cb(formatBody(0, '用户未注册'))
    let canUseRoom = await room.findOne({
      where: {
        type,
        coin,
        memberNum,
        state: '1'
      }
    })
    let roomId
    let { nickName, avatarUrl } = isExistUser
    if (canUseRoom) {
      let { memberNum, membersInfo, id, duration } = canUseRoom
      let nowLength = membersInfo.length
      roomId = id
      let userHasIn = false
      let members = []
      for (let i = 0; i < nowLength; i++) {
        members.push(membersInfo[i].uid)
        if (uid === membersInfo[i].uid) {
          membersInfo[i] = {
            uid, nickName, avatarUrl
          }
          userHasIn = true
          break
        }
      }
      // if (userHasIn) return cb(formatBody(0, '已有正在匹配的房间'))
      if (nowLength < (+memberNum)) {
        if (!userHasIn) {
          membersInfo.push({
            uid, nickName, avatarUrl
          })
          members.push(uid)
          nowLength++
        }
        socket.join(roomId)
        io.to(roomId).emit('memberChange', {
          roomId,
          memberNum,
          membersInfo
        })
      }
      if (nowLength === +memberNum) {
        const body = {
          roomId,
          code: game.checkCode,
          userList: members, // JSON.stringify(members),
          price: canUseRoom.coin,
          isToolAvailable: canUseRoom.type == 2 ? true : false
        }
        console.log('匹配成功body=>', JSON.stringify(body))
        let coinCutOk = false
        await rp({
          method: 'POST',
          uri: game.baseUrl + '/post_start_a_new_room_wx',
          body,
          json: true
        }).then(res => {
          console.log(res)
          if (res.ReturnCode === 'SUCCESS') coinCutOk = true
        }).catch(err => {
          console.log('err', err)
        })
        if (coinCutOk) {
          await room.update({
            state: '2'
          }, {
            where: { id: roomId }
          })
          io.to(roomId).emit('matchSuccess', { membersInfo, duration, roomId, type: canUseRoom.type, coin: canUseRoom.coin })
          setTimeout(async () => {
            // 如果没有提前结束
            const nowRoom = await room.findOne({
              where: { id: roomId }
            })
            if (nowRoom.state !== '3') {
              await room.update({
                state: '3'
              }, {
                where: { id: roomId }
              })
              io.to(roomId).emit('gameOver', { roomId, membersInfo: nowRoom.membersInfo })
              let sendCoinOk = false
              let sendMemberInfo = nowRoom.membersInfo.map(item => {
                return {
                  openid: item.uid,
                  score: item.score,
                  duration: item.duration
                }
              })
              const body1 = {
                roomId,
                code: game.checkCode,
                memberInfo: sendMemberInfo
              }
              console.log('结算参数=>', JSON.stringify(body1))
              let bonus
              await rp({
                method: 'POST',
                uri: game.baseUrl + '/post_get_game_bonus_by_room_id_new',
                body: body1,
                json: true
              }).then(res => {
                console.log(res)
                if (res.ReturnCode === 'SUCCESS') {
                  bonus = res.bonus
                  sendCoinOk = true
                }
              }).catch(err => {
                console.log('err', err)
              })
              io.to(roomId).emit('sendCoinOk', { status: sendCoinOk ? 1 : 0, membersInfo: nowRoom.membersInfo, bonus,  message: '游戏结算成功' })
            }
          }, +duration || 60 * 1000)
        } else {
          io.to(roomId).emit('matchFail', { message: '积分扣减异常' })
        }
      }
      await room.update({
        membersInfo: JSON.stringify(membersInfo),
        members: JSON.stringify(members)
      }, {
        where: { id }
      })
    } else {
      let newRoom = await room.create({
        id: nanoid(),
        type,
        coin,
        memberNum,
        duration: +duration,
        creator: uid + '',
        members: JSON.stringify([uid]),
        membersInfo: JSON.stringify([{ uid, nickName, avatarUrl }]),
        state: '1'
      })
      roomId = newRoom.id
      socket.join(roomId)
      io.to(roomId).emit('memberChange', {
        roomId,
        memberNum,
        membersInfo: [{ uid, nickName, avatarUrl }]
      })
    }
    await user.update({
      lastRoom: roomId
    }, {
      where: { uid }
    })
    return cb(formatBody(1, '加入成功', { roomId }))
  },
  async doubleMatch(data, socket, cb, io) {
    // console.log('doubleMatch', data)
    // 先查找所有处于匹配状态的人 然后取n个加入群组
    let { uid, roomId } = data
    if (!uid || !roomId) return cb(formatBody(0, 'uid,roomId参数不可为空'))
    const isExistUser = await user.findOne({
      where: { uid }
    })
    if (!isExistUser) return cb(formatBody(0, '用户未注册'))
    let isExistRoom = await room.findOne({
      where: { id: roomId }
    })
    let { nickName, avatarUrl } = isExistUser
    if (isExistRoom) {
      let { members, memberNum, membersInfo, duration, coin, state } = isExistRoom
      // let memberNum = JSON.parse(members).length
      if (state != '1') return cb(formatBody(0, '本局对战已经结束，请重新发起'))
      if (members.indexOf(uid) === -1) {
        return cb(formatBody(0, '此房间为专属对战房间，你没有进入权限'))
      } else {
        let userHasIn = false
        let memberLen = membersInfo.length
        for (let i = 0; i < memberLen; i++) {
          if (uid === membersInfo[i].uid) {
            membersInfo[i] = { uid, nickName, avatarUrl }
            userHasIn = true
            break
          }
        }
        if (!userHasIn) {
          membersInfo.push({ uid, nickName, avatarUrl })
          memberLen++
        }
        await user.update({
          lastRoom: roomId
        }, {
          where: { uid }
        })
        await room.update({
          membersInfo: JSON.stringify(membersInfo)
        }, {
          where: { id: roomId }
        })
        socket.join(roomId)
        io.to(roomId).emit('memberChange', {
          roomId,
          memberNum,
          membersInfo
        })
        cb(formatBody(1, '加入成功'))
        console.log(`doubleMatch=======memberLen${memberLen}|memberNum${memberNum}`)
        if (memberLen == memberNum) {
          // console.log(roomId, members, members, game.checkCode)
          const body = {
            roomId,
            code: game.checkCode,
            userList: members,
            price: coin,
            isToolAvailable: isExistRoom.type == 2 ? true : false
          }
          console.log('匹配成功=>', JSON.stringify({
            roomId,
            memberNum,
            membersInfo
          }))
          let coinCutOk = false
          await rp({
            method: 'POST',
            uri: game.baseUrl + '/post_start_a_new_room_wx',
            body,
            json: true
          }).then(res => {
            console.log(res)
            if (res.ReturnCode === 'SUCCESS') coinCutOk = true
          }).catch(err => {
            console.log('err', err)
          })
          if (coinCutOk) {
            // socket.join(roomId)
            await room.update({
              state: '2'
            }, {
              where: { id: roomId }
            })
            io.to(roomId).emit('matchSuccess', { membersInfo, duration, roomId, type: isExistRoom.type, coin })
            setTimeout(async () => {
              const nowRoom = await room.findOne({
                where: { id: roomId }
              })
              // 如果没有提前结束
              if (nowRoom.state !== '3') {
                await room.update({
                  state: '3'
                }, {
                  where: { id: roomId }
                })
                io.to(roomId).emit('gameOver', { roomId, membersInfo: nowRoom.membersInfo })
                let sendCoinOk = false
                let sendMemberInfo = nowRoom.membersInfo.map(item => {
                  return {
                    openid: item.uid,
                    score: item.score,
                    duration: item.duration
                  }
                })
                const body1 = {
                  roomId,
                  code: game.checkCode,
                  memberInfo: sendMemberInfo
                }
                console.log('结算参数=>', JSON.stringify(body1))
                let bonus
                await rp({
                  method: 'POST',
                  uri: game.baseUrl + '/post_get_game_bonus_by_room_id_new',
                  body: body1,
                  json: true
                }).then(res => {
                  console.log(res)
                  if (res.ReturnCode === 'SUCCESS') {
                    bonus = res.bonus
                    sendCoinOk = true
                  }
                }).catch(err => {
                  console.log('err', err)
                })
                io.to(roomId).emit('sendCoinOk', { status: sendCoinOk ? 1 : 0, membersInfo: nowRoom.membersInfo, bonus, message: '游戏结算成功' })
              }
            }, duration)
          } else {
            io.to(roomId).emit('matchFail', { message: '积分扣减异常' })
          }
        }
      }
    } else {
      cb(formatBody(0, '房间不存在或已经被销毁'))
    }
    return cb(formatBody(1, '加入成功', { roomId }))
  },
  async message(data, socket, cb, io) {
    let { roomId, uid, score, state, duration, tools } = data
    console.log('message=>', JSON.stringify(data))
    let isExistRoom = await room.findOne({
      where: { id: roomId }
    })
    let isExistUser = await user.findOne({
      where: { uid }
    })
    if (!isExistRoom || !isExistUser) {
      return cb(formatBody(0, '房间或者用户不存在'))
    } else {
      if (isExistRoom.state !== '2') return cb(formatBody(0, '对战已经结束'))
      let { nickName, avatarUrl } = isExistUser
      let { membersInfo, memberNum } = isExistRoom
      let len = membersInfo.length
      for (let i = 0; i < len; i++) {
        if (membersInfo[i].uid === uid) {
          membersInfo[i] = Object.assign({}, membersInfo[i], { nickName, avatarUrl, score, state, duration, tools })
          break
        }
      }
      let overNum = 0
      membersInfo.forEach(item => {
        if (+item.state === 3) {
          overNum++
        }
      })
      let stateObj = {}
      console.log(`overNum: ${overNum} len: ${len}`, JSON.stringify(membersInfo))
      if (overNum === len) stateObj = { state: '3' }
      await room.update({
        membersInfo: JSON.stringify(membersInfo),
        ...stateObj
      }, {
        where: { id: roomId }
      })
      if (overNum === len) {
        if (isExistRoom.state === '3') return
        io.to(roomId).emit('gameOver', { roomId, membersInfo })
        console.log('开始结算')
        let sendCoinOk = false
        let sendMemberInfo = membersInfo.map(item => {
          return {
            openid: item.uid,
            score: item.score,
            duration: item.duration
          }
        })
        const body1 = {
          roomId,
          code: game.checkCode,
          memberInfo: sendMemberInfo
        }
        console.log('结算参数=>', JSON.stringify(body1))
        let bonus
        await rp({
          method: 'POST',
          uri: game.baseUrl + '/post_get_game_bonus_by_room_id_new',
          body: body1,
          json: true
        }).then(res => {
          console.log(res)
          if (res.ReturnCode === 'SUCCESS') {
            bonus = res.bonus
            sendCoinOk = true
          }
        }).catch(err => {
          console.log('err', err)
        })
        io.to(roomId).emit('sendCoinOk', { status: sendCoinOk ? 1 : 0, membersInfo, bonus, message: '游戏结算成功' })
      } else {
        console.log('推送消息到客户端', { roomId, membersInfo })
        io.to(roomId).emit('memberChange', { roomId, memberNum, membersInfo })
      }
      return cb(formatBody(1, 'ok', { membersInfo }))
    }
  },
  async leaveRoom (data, socket, cb, io) {
    const { uid, roomId } = data
    if (!uid || !roomId) {
      return cb(formatBody(0, 'uid,roomId不可为空'))
    }
    let hasUser = await user.findOne({
      where: { uid }
    })
    let lastRoom = await room.findOne({
      where: { id: roomId }
    })
    if (hasUser && lastRoom) {
      let { membersInfo, members, type, memberNum } = lastRoom
      let len = membersInfo.length
      // 如果离开的时候房间还在匹配中
      
      for (let i = 0; i < len; i++) {
        if (membersInfo[i].uid === hasUser.uid) {
          if (lastRoom.state === '1') {
            membersInfo.splice(i, 1)
            if (type !== '3') members.splice(i, 1)
          }
          if (lastRoom.state === '2') {
            membersInfo[i].state = '3'
          }
          break
        }
      }
      await user.update({
        lastGroup: ''
      }, {
        where: { uid }
      })
      await room.update({
        members: JSON.stringify(members),
        membersInfo: JSON.stringify(membersInfo)
      }, {
        where: { id: roomId }
      })
      socket.leave(roomId)
      io.to(roomId).emit('memberChange', {
        roomId, membersInfo, memberNum
      })
      return cb(formatBody(1, '离开成功'))
    } else {
      return cb(formatBody(0, '房间或者用户不存在'))
    }
  },
  async disconnect (data, socket, cb, io) {
    let hasUser = await user.findOne({
      where: {
        socketId: socket.id
      }
    })
    if (hasUser) {
      await user.update({
        isOnLine: 0
      }, {
        where: {
          socketId: socket.id
        }
      })
      const roomId = hasUser.lastRoom
      console.log('=====disconnect', socket.id, '=====roomId', roomId)
      if (roomId) {
        let lastRoom = await room.findOne({
          where: { id: roomId }
        })
        if (lastRoom) {
          let { membersInfo, members, type, memberNum } = lastRoom
          let len = membersInfo.length
          // 如果离开的时候房间还在匹配中
          if (lastRoom.state === '1') {
            for (let i = 0; i < len; i++) {
              if (membersInfo[i].uid === hasUser.uid) {
                membersInfo.splice(i, 1)
                if (type !== '3') members.splice(i, 1)
                break
                
              }
            }
          }
          let overNum = 0
          if (lastRoom.state === '2') {
            for (let i = 0; i < len; i++) {
              if (membersInfo[i].uid === hasUser.uid) {
                // 非双人对战房间 不能改变members
                membersInfo[i].state = '3'
              }
              if (membersInfo[i].state && membersInfo[i].state === '3') {
                overNum++
              }
            }
          }
          let roomStateObj = {}
          if (overNum === len) {
            roomStateObj = {
              state: '3'
            }
            let sendMemberInfo = membersInfo.map(item => {
              return {
                openid: item.uid,
                score: item.score || 0,
                duration: item.duration
              }
            })
            const body1 = {
              roomId,
              code: game.checkCode,
              memberInfo: sendMemberInfo
            }
            console.log('结算参数=>', JSON.stringify(body1))
            await rp({
              method: 'POST',
              uri: game.baseUrl + '/post_get_game_bonus_by_room_id_new',
              body: body1,
              json: true
            }).then(res => {
              console.log(res)
              if (res.ReturnCode === 'SUCCESS') {
                console.log('结算成功', res)
              }
            }).catch(err => {
              console.log('err', err)
            })
          }
          await user.update({
            lastGroup: ''
          }, {
            where: { socketId: socket.id }
          })
          await room.update({
            members: JSON.stringify(members),
            membersInfo: JSON.stringify(membersInfo),
            ...roomStateObj
          }, {
            where: { id: roomId }
          })
          socket.leave(roomId)
          io.to(roomId).emit('memberChange', {
            roomId, memberNum, membersInfo
          })
        }
      }
    }
  },
  async createDoubleRoom (ctx) {
    const { creator, members, coin } = ctx.request.body
    console.log(creator, members, coin)
    if (!creator || !members || !coin) return ctx.body = formatBody(0, 'creator,members,coin为必传参数')
    try {
      JSON.parse(members)
    } catch {
      return ctx.body = formatBody(0, 'members格式错误')
    } 
    if (members.indexOf(creator) === -1) {
      return ctx.body = formatBody(0, '房主不在成员列表')
    }
    const newRoom = await room.create({
      id: nanoid(),
      type: '3',
      coin: +coin,
      memberNum: '2',
      duration: 60 * 1000,
      creator,
      members: members,
      membersInfo: JSON.stringify([]),
      state: '1'
    })
    setTimeout(async () => {
      const nowRoom = await room.findOne({
        where: { id: newRoom.id }
      })
      // 如果60s之后游戏还是没开始，删掉房间
      if (nowRoom.state === '1') {
        await room.destroy({
          where: {
            id: newRoom.id
          }
        })
      }
    }, 600 * 1000)
    return ctx.body = formatBody(1, '创建成功', {
      roomId: newRoom.id
    })
  },
  async createRoom (ctx) {
    const { creator, members, coin, type } = ctx.request.body
    if (!creator || !members || !coin) return ctx.body = formatBody(0, 'creator,members,coin为必传参数')
    try {
      JSON.parse(members)
    } catch {
      return ctx.body = formatBody(0, 'members格式错误')
    } 
    if (members.indexOf(creator) === -1) {
      return ctx.body = formatBody(0, '房主不在成员列表')
    }
    const memberNum = JSON.parse(members).length
    console.log('createRoom=>', `members: ${members}<>coin: ${coin}<> memberNum: ${memberNum}`)
    const newRoom = await room.create({
      id: nanoid(),
      type,
      coin: +coin,
      memberNum,
      duration: 60 * 1000,
      creator,
      members: members,
      membersInfo: JSON.stringify([]),
      state: '1'
    })
    setTimeout(async () => {
      const nowRoom = await room.findOne({
        where: { id: newRoom.id }
      })
      // 如果60s之后游戏还是没开始，删掉房间
      if (nowRoom.state === '1') {
        await room.destroy({
          where: {
            id: newRoom.id
          }
        })
      }
    }, 60 * 1000)

    return ctx.body = formatBody(1, '创建成功', {
      roomId: newRoom.id
    })
  }
}
